<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>多个属性描述符</title>
  <!-- 
  在JavaScript中，多个属性描述符（Multiple Property Descriptors）允许在对象上同时定义或修改多个属性的特性。通过使用  `Object.defineProperties()`  方法，可以一次性定义多个属性及其描述符。这在需要对对象进行批量操作时非常有用。
  一、属性描述符的组成
  属性描述符可以是数据属性描述符或存取属性描述符：
  1. 数据属性描述符：
    - value：属性的值。
    - writable：一个布尔值，指示属性值是否可写。
    - enumerable：一个布尔值，指示属性是否可枚举。
    - configurable：一个布尔值，指示属性是否可配置。

  2. 存取属性描述符：
    - get：获取属性值的函数。
    - set：设置属性值的函数。
    - enumerable：一个布尔值，指示属性是否可枚举。
    - configurable：一个布尔值，指示属性是否可配置。

  二、使用  `Object.defineProperties()` 
  `Object.defineProperties()`  方法接受两个参数：目标对象和一个描述符对象，其中描述符对象可以包含多个属性及其对应的描述符。
  const person = {};

  Object.defineProperties(person, {
      firstName: {
          value: 'John',
          writable: true,
          enumerable: true,
          configurable: true
      },
      lastName: {
          value: 'Doe',
          writable: false, // 不可写
          enumerable: true,
          configurable: true
      },
      fullName: {
          get() {
              return `${this.firstName} ${this.lastName}`;
          },
          enumerable: true,
          configurable: true
      }
  });

  // 访问属性
  console.log(person.fullName); // 输出: John Doe

  // 修改可写属性
  person.firstName = 'Jane';
  console.log(person.fullName); // 输出: Jane Doe

  // 尝试修改不可写属性
  person.lastName = 'Smith'; // 无法修改
  console.log(person.lastName); // 输出: Doe

  三、注意事项
  1. 批量定义：
    - 使用  `Object.defineProperties()`  可以方便地批量定义多个属性，避免多次调用  `Object.defineProperty()` 。

  2. 可枚举和可配置：
    - 在定义多个属性时，可以灵活设置每个属性的  `enumerable`  和  `configurable`  特性，以控制属性的可见性和可修改性。

  3. 性能：
    - 批量定义属性时，性能可能会更好，因为浏览器可以优化处理过程。

  四、总结
  - 多个属性描述符允许在对象上同时定义或修改多个属性的特性。
  - 使用  `Object.defineProperties()`  方法可以批量定义多个属性及其描述符，提高代码的可读性和维护性。
  - 理解属性描述符的特性（如  `writable` 、 `enumerable`  和  `configurable` ）有助于更好地控制对象的行为。

   -->
</head>

<body>

  <script>
    // 定义一个对象
    const person = {
      firstName: 'John',
      lastName: 'Doe'
    };

    // 定义多个属性描述符
    Object.defineProperties(person, {
      firstName: {
        value: 'John',
        writable: true,
        enumerable: true,
        configurable: true
      },
      lastName: {
        value: 'Doe',
        writable: false,
        enumerable: true,
        configurable: true
      },
      fullName: {
        get() {
          return `${this.firstName} ${this.lastName}`;
        },
        set(value) {
          const parts = value.split(' ');
          this.firstName = parts[0];
          this.lastName = parts[1];
        },
        enumerable: true,
        configurable: true
      }
    });

    console.log(person.fullName); // John Doe
    person.fullName = 'Jane Smith';
    console.log(person.fullName); // Jane Smith
    console.log(person.firstName); // Jane
    console.log(person.lastName); // Smith
  </script>

</body>

</html>